/**
 *
 */

import { isArray, isNumber, isObject, isString, isBoolean } from 'fc-cli-core'
import FCRuleFactorValue from './FCRuleFactorValue'
import style, { styleArray } from './FCRuleTableStyle'

const styleKey = '$highlight'

class FCRule {
  /* properties */

  key
  // table
  // values = {}
  valueObjMap = {}

  // #factorValues = {}
  // #style = {}

  /* life cycle */

  constructor({ key, factors, data } = {}) {
    this.key = key
    // this.table = table

    this.valueObjMap = this.buildValueObjMap({ data, factors })

    // this.#factorValues = this.buildFactorValues({ data, factors })
    // if (data[styleKey]) {
    //   this.#style = this.buildFactorStyles({ styleData: data[styleKey], factors })
    // }
  }

  buildValueObjMap({ data = {}, factors = [] } = {}) {
    const map = {}

    factors.forEach((factor) => {
      const { code } = factor
      if (data.hasOwnProperty(code)) {
        const valueObj = new FCRuleFactorValue({
          key: this.createNewValueKey(),
          factor,
          value: data[code],
        })
        map[code] = valueObj
      }
    })

    return map
  }

  setValueObj(key, obj) {
    this.valueObjMap[key] = obj
  }

  getValueObj(key) {
    return this.valueObjMap[key]
  }

  // buildFactorStyles({ styleData = {}, factors = [] } = {}) {
  //   const styles = {}

  //   for (let i = 0; i < factors.length; i++) {
  //     const factor = factors[i]
  //     const { code } = factor

  //     if (!styleData.hasOwnProperty(code)) {
  //       continue
  //     }

  //     let factorStyle = styleData[code]

  //     if (isBoolean(factorStyle) && factorStyle) {
  //       factorStyle = styleArray[0]
  //     }

  //     if (isString(factorStyle)) {
  //       factorStyle = style[factorStyle]
  //     }

  //     styles[code] = factorStyle
  //   }

  //   // console.log('>>> styles is:', styles)

  //   return styles
  // }

  /* public methods */

  getLabel(code) {
    const factorValue = this.getValueObj(code)
    if (factorValue) {
      return factorValue.label || '-'
    }
    return '-'
  }

  getValue(code) {
    const valueObj = this.getValueObj(code)
    if (valueObj) {
      // todo: return valueString
      return valueObj.value
    }
  }

  getValues() {
    const values = {}
    Object.keys(this.valueObjMap).forEach((code) => {
      values[code] = this.getValue(code)
    })
    return values
  }

  setValue({ code, value }) {
    const factorValue = this.getValueObj(code)
    factorValue.value = value
  }

  getValueList(codeList = []) {
    return codeList.map((code) => this.getValue(code))
  }

  // getStyle(code) {
  //   return this.#style[code]
  // }

  hasFactor(factorCodes, mode = 'some') {
    if (mode === 'some') {
      return this.hasSomeFactor(factorCodes)
    } else if (mode === 'every') {
      return this.hasAllFactors(factorCodes)
    }

    // error
    console.log(`[hasFactor]: mode ${mode} is not support`)
    return false
  }

  hasSomeFactor(factorCodes = []) {
    factorCodes = isArray(factorCodes) ? factorCodes : [factorCodes]
    return factorCodes.some((code) => this.valueObjMap.hasOwnProperty(code))
  }

  hasAllFactors(factorCodes = []) {
    factorCodes = isArray(factorCodes) ? factorCodes : [factorCodes]
    return factorCodes.every((code) => this.valueObjMap.hasOwnProperty(code))
  }

  /* private methods */

  // 生成 value.key
  #valueIndex = 1
  createNewValueKey() {
    return `${this.key}-v:${this.#valueIndex++}`
  }
}

export default FCRule
